//promise是什么：Promise代表未来的一种状态变化，是一种异步变成的实现方案
//promise优点 ： 解决回调地狱 链式调用  统一错误处理
//promise 有三种状态 pendding fulfilled rejected
//状态变化 
    //只有pennding状态时，才可以改变状态 fulfilled/rejected
    //当状态变为fulfilled，状态不能再变化，必须有一个终值
    //当状态变为rejected，状态不能再变化，必须有一个失败原因
//then(onFulfilled,onRejected)
    //onFulfilled,onRejected为可选的参数
//静态方法：
   //Promise.resolve()
   //Promise.reject()
   //Promise.all()
   //Promise.race()
   //Promise.finally()
const PENDDING = 'pendding'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'

function resolvePromise(promise2,x,resolve,reject){
    //1、如果x是一个普通值，直接resolve
    //2、如果x是一个promise,则采用promise的状态来决定是成功还是失败
    if(x == promise2){   //避免循环引用
      return reject(new TypeError('循环引用'))
    }
    let called = false;  //避免多次调用
    if((x !==null && typeof x === 'object')|| (typeof x === 'function')){  //如果x是一个thenable对象或者函数
        try {
            let then = x.then;
            if(typeof then == 'function'){  //then是一个函数
                then.call(x,y=>{
                    if(called) return;
                    called = true
                    resolvePromise(promise2,y,resolve,reject)
                },r=>{
                    if(called) return;
                    called = true
                    reject(r)
                })
            }else{
               //普通对象 
               resolve(x) 
            }
        } catch (error) {
            if(called) return;
            called = true
            reject(error)  
        }
    }else{  //x是一个普通值，无论成功失败将传递给promise2成功回调
        resolve(x)
    }
}
class Promise {
    constructor(executor){
        this.state = PENDDING;
        this.value = undefined
        this.reason = undefined
        this.onResolvedCallbacks = []
        this.onRejectedCallbacks = [];

        const resolve = (value)=>{
            if(value instanceof Promise){   //Promise.resolve()静态方法调用时，保证有等待状态
               return value.then(resolve,reject)
            }
            if(this.state == PENDDING){  //状态只能从pendding变为FULFILLED、REJECTED
                this.state = FULFILLED;  
                this.value = value
                this.onResolvedCallbacks.forEach(fn=>fn(this.value))   //异步改变状态或多次执行promise时需要将回调缓存在数组，等待状态改变之后再执行
            }
        } 
        const reject = (reason)=>{
            if(this.state == PENDDING){
                this.state = REJECTED 
                this.reason = reason 
                this.onRejectedCallbacks.forEach(fn=>fn(this.reason))
            } 
        }
        try {
            executor(resolve,reject)
        } catch (error) {
            reject(error)   
        } 
    } 
    then(onFulfilled,onRejected){
        onFulfilled = typeof onFulfilled == 'function'? onFulfilled:value=>value;  //解决透传
        onRejected = typeof onRejected == 'function'? onRejected:reason=>{throw reason};
        let promise2  = new Promise((resolve,reject)=>{    //Promise.then必须返回一个promise,无论成功或者失败会将promise2的状态传递给下一个then
            if(this.state == FULFILLED){
                setTimeout(()=>{
                    try {  //如果onFulfilled或onRejected抛出一个异常e,则reject
                        let x = onFulfilled(this.value)   //如果onFulfilled或onRjected返回一个值x，运行promise解决程序[[Resolve]](promise2,x)
                        //then方法不论成功失败，如果返回一个 普通值x，将将结果传递给下一个then的成功回调
                        resolvePromise(promise2,x,resolve,reject)
                    } catch (error) {
                        reject(error)
                    } 
                })
            }
            if(this.state == REJECTED){
                setTimeout(()=>{
                    try { //如果onFulfilled或onRejected抛出一个异常e,则reject
                        let x = onRejected(this.reason)   //如果onFulfilled或onRjected返回一个值x，运行promise解决程序[[Resolve]](promise2,x)
                        resolvePromise(promise2,x,resolve,reject)
                    } catch (error) {
                        reject(error)
                    } 
                })
            }
            if(this.state == PENDDING){
//console.log('pendding状态等待状态')
                this.onResolvedCallbacks.push((value)=>{
                    setTimeout(()=>{
                        try {
                            let x = onFulfilled(value)
                            resolvePromise(promise2,x,resolve,reject)
                        } catch (error) {
                            reject(error)   
                        }
                    })
                })
                this.onRejectedCallbacks.push((reason)=>{
                    setTimeout(()=>{
                        try {
                            let x = onRejected(reason)
                            resolvePromise(promise2,x,resolve,reject)
                        } catch (error) {
                            reject(error)
                        }
                    })
                })
            }
        })
        return promise2
    } 
    catch(errFn){
        return this.then(null,errFn)
    }
    //Promise.resolve()具备等待效果
    static resolve(value){
        return new Promise((resolve,reject)=>{
           resolve(value) 
        })
    }
    static reject(reason){
        return new Promise((resolve,reject)=>{
            reject(reason) 
         })
    }
    static all(promises){
        let count = 0;
        let result = [];
        return new Promise((resolve,reject)=>{
            if(Array.isArray(promises)){
                promises.forEach((promise,index)=>{
                    Promise.resolve(promise).then((value)=>{
                        count++
                        result[index] = value
                        if(promises.length == count){
                            resolve(result)
                        } 
                    },(error)=>{
                        reject(error)
                    })
                })   
            }else{
                throw TypeError('参数类型错误')
            }
        }) 
    }
    static allSettled(){

    }
    static race(){

    } 
    static catch(){

    }
    static finally(){

    }    
    static deferred () { // 延迟对象
        let defer = {};
        defer.promise = new Promise((resolve, reject) => {
            defer.resolve = resolve;
            defer.reject = reject;
        });
        return defer;
    }
}

//测试1: 
// let promise = new Promise((resolve,reject)=>{
// //    测试1: resolve/reject 状态改变之后就不再改变 
// //    resolve(1)
// //    reject(new Error('出错了'))

// //    测试2: 状态为等待态，会推入队列，等待状态变化后依次执行
//     setTimeout(()=>{
//         resolve(1)
//     })
// })
// promise.then((value)=>{
//     console.log(value,new Date())
// },(err)=>{
//     console.log(err)
// })
// 测试3：同一个promise.可以多次执行then,返回相同的结果
// promise.then((value)=>{
//     console.log(value,new Date())
// },(err)=>{
//     console.log(err)
// })
// 测试4: 透传现象
// promise.then().then().then((value)=>{
//     console.log(value)
// })



//题目：Promise错误处理
// try {
//     new Promise((resolve,reject)=>{
//         throw new Error('错误处理')
//     }).then((res)=>{
//         console.log('第一个then',res)
//     })
// } catch (error) {
//     console.log(error)
// }

// Promise.all([1,2,3,,5]).then((res)=>{
//     console.log(res)
// })

    
//题目1:  结果：0123456
Promise.resolve().then(() => {
    console.log(0);
    return Promise.resolve(4);
}).then((res) => {
    console.log(res)
})
Promise.resolve().then(() => {
    console.log(1);
}).then(() => {
    console.log(2);
}).then(() => {
    console.log(3);
}).then(() => {
    console.log(5);
}).then(() =>{
    console.log(6);
})

//Promise.all错误捕获
// let p1 = new Promise((resolve,reject)=>{
//    throw Error('我错了1')
// }).catch((err)=>{
//     console.log(err)
// })
// let p2 = new Promise((resolve,reject)=>{
//     throw Error('我错了2')
//  }).catch((err)=>{
//      console.log(err)
//  })
//  Promise.all([p1,p2]).catch((err)=>{
//     console.log('错误信息输出',err)
//  })
module.exports = Promise;

